/**
 *  Copyright (c) 2012-2014 http://www.eryansky.com
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.wolfeyes.common.utils.character;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @title 字符串工具类，用于实现一些字符串的常用操作 
 * @author yanyljava 
 * @date 2014-11-17 下午8:02:31
 */
public class CommonUtils extends org.apache.commons.lang3.StringUtils {

    public static final String NUMBERS_AND_LETTERS         = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String NUMBERS                     = "0123456789";
    public static final String LETTERS                     = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String CAPITAL_LETTERS             = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String LOWER_CASE_LETTERS          = "abcdefghijklmnopqrstuvwxyz";

    public static final String defaultKeyAndValueSeparator = ":";
    public static final String defaultValueEntitySeparator = ",";
    public static final String defaultKeyOrValueQuote      = "\"";

    /**
     * 判断字符串是否为空或长度为0
     * 
     * @param str
     * @return 若字符串为null或长度为0, 返回true; 否则返回false.
     * 
     * <pre>
     *      isEmpty(null)   =   true;
     *      isEmpty("")     =   true;
     *      isEmpty("  ")   =   false;
     * </pre>
     */
    public static boolean isEmpty(String str) {
    	
        return (str == null || str.length() == 0);
    }
   
    
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }
    /**
      * 判断一个对象是否不为空 
      *              
      * @param @param obj
      * @param @return
      *              本参数解释   
      * @return boolean    
      * @throws
     */
    public static boolean isNotNull(Object obj) {
    	if (obj == null ) {
    		return false;
    	} else {
    		return true;
    	}
    }

    public static boolean ToListIsNotNull(Map map) {
    	List list = (List) map.get("userData");
    	if(list.size() == 0) {
    		return false;
    	}else {
    		return true;
    	}
    }
    /**
     * 判断一个对象是否为空 
     *              
     * @param @param obj
     * @param @return
     *              本参数解释   
     * @return boolean    
     * @throws
    */
   public static boolean isNull(Object obj) {
   	if (obj == null) {
   		return true;
   	} else {
   		return false;
   	}
   }
    /**
      * 比较两个Long类型              
      * @param long1
      * @param long2
      * @return boolean 
      * @Author chensg
      * @date 2014-11-22 下午6:17:34    
      * @throws
     */
    public static boolean isEqualByLong(Long long1, Long long2) {
    	if(isNull(long1) && isNotNull(long2) || isNotNull(long1) && isNull(long2)) {
    		return false;
    	}
    	
    	if(isNull(long1) && isNull(long2)) {
    		return true;
    	}
    	
    	if(long1.longValue() == long2.longValue()) {
    		return true;
    	} else {
    			return false;
    	}
    }
    
    /**
     * 比较两个Integer类型
     * @return boolean 
     * @Author chensg
     * @date 2014-11-22 下午6:17:34    
     * @throws
    */
   public static boolean isEqualByInteger(Integer int1, Integer int2) {
   	
	   //其中有一个为空值时，则返回false;
	   if(isNull(int1) && isNotNull(int2) || isNotNull(int1) && isNull(int2)) {
		   return false;
	   }
	   //如果两个都为空值,则认为相同，返回true
	   if(isNull(int1) && isNull(int2)) {
		   return true;
	   }
	   
	   if(int1.intValue() == int2.intValue()) {
		   return true;
	   } else {
		   return false;
	   }
   }
   public static boolean isEqualByDate(Date date1, Date date2, String formate) {
	   
	   if(isNull(date1) && isNotNull(date2) || isNotNull(date1) && isNull(date2)) {
		   return false;
	   }
	   if(isNull(date1) && isNull(date2)) {
		   return true;
	   }
	   SimpleDateFormat format = new SimpleDateFormat(formate);
	   if(format.format(date1).equals(format.format(date2))) {
		   return true;
	   }
	   return false;
	   
   }
   /**
    * 比较两个String类型
    * @return boolean 
    * @Author chensg
    * @date 2014-11-22 下午6:17:34    
    * @throws
   */
  public static boolean isEqualByString(String str1, String str2) {
	   //其中有一个为空值时，则返回false;
	   if(isBlank(str1) && isNotBlank(str2) || isNotBlank(str1) && isBlank(str2)) {
		   return false;
	   }
	   //如果两个都为空值,则认为相同，返回true
	   if(isBlank(str1) && isBlank(str2)) {
		   return true;
	   }
	   
	   if(str1.equals(str2)) {
		   return true;
	   } else {
		   return false;
	   }
  }
    /**
      * Integer类型转换为String类型              
      * @param long1
      * @return String 
      * @Author chensg
      * @date 2014-12-26 下午8:34:36    
      * @throws
     */
	public static String long2String(Long long1) {
	   if(isNotNull(long1)) {
		   return String.valueOf(long1);
	   } else {
		   return "";
	   }
    }
	
	/**
     * Long类型转换为String类型
     * @return String 
     * @Author chensg
     * @date 2014-12-26 下午8:34:36    
     * @throws
    */
	public static String int2String(Integer int1) {
	   if(isNotNull(int1)) {
		   return String.valueOf(int1);
	   } else {
		   return "";
	   }
   }
   
    /**
     * 判断字符串是否为空或长度为0，或仅由空格组成
     * 
     * @param str
     * @return 若字符串为null或长度为0或仅由空格组成, 返回true; 否则返回false.
     * 
     * <pre>
     *      isBlank(null)   =   true;
     *      isBlank("")     =   true;
     *      isBlank("  ")   =   true;
     *      isBlank("a")    =   false;
     *      isBlank("a ")   =   false;
     *      isBlank(" a")   =   false;
     *      isBlank("a b")  =   false;
     * </pre>
     */
    public static boolean isBlank(String str) {
        return (isEmpty(str) || (str.trim().length() == 0));
    }

    public static boolean isNotBlank(String str) {
    	return !isBlank(str);
    }
    
    @SuppressWarnings("null")
	public static boolean listIsNull(List list) {
    	if(list == null || list.size() == 0) {
    		return true;
    	} else {
    		return false;
    	}
    }
    public static boolean listIsNotNull(List list) {
    	if(list == null || list.size() == 0) {
    		return false;
    	} else {
    		return true;
    	}
    }
    /**
     * 将字符串首字母大写后返回
     * 
     * @param str 原字符串
     * @return 首字母大写后的字符串
     * 
     * <pre>
     *      capitalizeFirstLetter(null)     =   null;
     *      capitalizeFirstLetter("")       =   "";
     *      capitalizeFirstLetter("1ab")    =   "1ab"
     *      capitalizeFirstLetter("a")      =   "A"
     *      capitalizeFirstLetter("ab")     =   "Ab"
     *      capitalizeFirstLetter("Abc")    =   "Abc"
     * </pre>
     */
    public static String capitalizeFirstLetter(String str) {
        return (isEmpty(str) || !Character.isLetter(str.charAt(0))) ? str : Character.toUpperCase(str.charAt(0))
                                                                            + str.substring(1);
    }
    /**
     *描述：将LISt用逗号隔开
     *@Author yuk
     *@Date 2016/11/26 13:09
     *@return
     */
    public static <T> String listToString(List<T> list) {
        String ret = null;
        if(list != null) {
            StringBuffer strBuf = new StringBuffer("");
            Iterator i$ = list.iterator();

            while(i$.hasNext()) {
                Object t = i$.next();
                strBuf.append(t.toString().trim()+",");
            }

            ret = strBuf.toString();
            //去除最后一个逗号
            if(ret.length() > 0) {
                String last = ret.substring(ret.length()-1,ret.length());
                if(last.equals(",")) {
                    ret = ret.substring(0,ret.length()-1);
                }
            }

        }
        return ret;
    }
    /**
     * 如果不是普通字符，则按照utf8进行编码
     * 
     * @param str 原字符
     * @return 编码后字符，编码错误返回null
     * 
     * <pre>
     *      utf8Encode(null)        =   null
     *      utf8Encode("")          =   "";
     *      utf8Encode("aa")        =   "aa";
     *      utf8Encode("啊啊啊啊")   = "编码后字符";
     * </pre>
     */
    public static String utf8Encode(String str) {
        if (!isEmpty(str) && str.getBytes().length != str.length()) {
            try {
                return URLEncoder.encode(str, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return null;
            }
        }
        return str;
    }

    /**
     * 如果不是普通字符，则按照utf8进行编码，编码异常则返回defultReturn
     * 
     * @param str 源字符串
     * @param defultReturn 默认出错返回
     * @return
     */
    public static String utf8Encode(String str, String defultReturn) {
        if (!isEmpty(str) && str.getBytes().length != str.length()) {
            try {
                return URLEncoder.encode(str, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                return defultReturn;
            }
        }
        return str;
    }

    /**
     * null字符串转换为长度为0的字符串
     * 
     * @param str 待转换字符串
     * @return
     * @see
     * <pre>
     *  nullStrToEmpty(null)    =   "";
     *  nullStrToEmpty("")      =   "";
     *  nullStrToEmpty("aa")    =   "";
     * </pre>
     */
    public static String nullStrToEmpty(String str) {
        return (str == null ? "" : str);
    }

    /**
     * 以固定格式得到当前时间的字符串
     * 
     * @param format 时间格式，同时间的format，如"yyyy-MM-dd HH:mm:ss"
     * @return 时间字符串，若format为空或长度为空或只包含空格，则默认为"yyyy-MM-dd HH:mm:ss"
     * 
     * <pre>
     *      currentDate(null)                   = "yyyy-MM-dd HH:mm:ss"
     *      currentDate("")                     = "yyyy-MM-dd HH:mm:ss"
     *      currentDate("   ")                  = "yyyy-MM-dd HH:mm:ss"
     *      currentDate("yyyy-MM-dd")           = "yyyy-MM-dd"
     *      currentDate("yyyy/MM/dd HH:mm:ss")  = "yyyy/MM/dd HH:mm:ss"
     * </pre>
     */
    public static String currentDate(String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(isBlank(format) ? "yyyy-MM-dd HH:mm:ss" : format);
        return dateFormat.format(new Date());
    }

    /**
     * 以"yyyy-MM-dd HH:mm:ss"格式得到当前时间
     * 
     * @return "yyyy-MM-dd HH:mm:ss"
     */
    public static String currentDate() {
        return currentDate("");
    }

    /**
     * 以固定格式得到当前时间的字符串，包含毫秒
     * 
     * @param format 时间格式，同时间的format，如"yyyy-MM-dd HH:mm:ss SS"
     * @return 时间字符串，若format为空或长度为空或只包含空格，则默认为"yyyy-MM-dd HH:mm:ss SS"
     * 
     * <pre>
     *      currentDate(null)                   = "yyyy-MM-dd HH:mm:ss SS"
     *      currentDate("")                     = "yyyy-MM-dd HH:mm:ss SS"
     *      currentDate("   ")                  = "yyyy-MM-dd HH:mm:ss SS"
     *      currentDate("yyyy-MM-dd")           = "yyyy-MM-dd"
     *      currentDate("yyyy/MM/dd HH:mm:ss SS")  = "yyyy/MM/dd HH:mm:ss SS"
     * </pre>
     */
    public static String currentDateInMills(String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(isBlank(format) ? "yyyy-MM-dd HH-mm-ss SS" : format);
        return dateFormat.format(new Timestamp(System.currentTimeMillis()));
    }

    /**
     * 以"yyyy-MM-dd HH:mm:ss SS"格式得到当前时间
     * 
     * @return "yyyy-MM-dd HH:mm:ss SS"
     */
    public static String currentDateInMills() {
        return currentDateInMills("");
    }
    /**
     * 
     * @Description:根据时间转为字符串 yyyy-MM-dd HH:mm:ss
     * @author yk
     * @Version: V1.00
     * 创建时间：2014-11-29 下午2:37:17
     * @param date
     * @return
     */
     public static String getDateToString(Date date) {
    	 SimpleDateFormat sdf =   new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
    	 if(date != null){
    		 return sdf.format(date);
    	 }else {
    		 return null;
		}
    }
    public static Date getStringToDate(String date) throws ParseException{
        SimpleDateFormat sdf =   new SimpleDateFormat( "yyyy-MM-dd");
        return sdf.parse(date);
    }
     /**
      * 
      * @Description:根据时间转为字符串 yyyy-MM-dd
      * @author yk
      * @Version: V1.00
      * 创建时间：2014-11-29 下午2:37:17
      * @param date
      * @return
      */
      public static String getDateToYMD(Date date) {
     	 SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd");
     	 if(date != null){
     		 String[] data=  sdf.format(date).split(" ");
     		 return data[0];
     	 }else {
     		 return null;
 		}
     }
    /**
     * 处理时间，用来显示状态更新时间
     * 
     * @param time
     * @return
     */
    @SuppressWarnings("deprecation")
    public static String processTime(Long time) {
        long oneDay = 24 * 60 * 60 * 1000;
        Date now = new Date();
        Date orginalTime = new Date(time);
        long nowDay = now.getTime() - (now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds()) * 1000;
        long yesterday = nowDay - oneDay;
        String nowHourAndMinute = toDoubleDigit(orginalTime.getHours()) + ":" + toDoubleDigit(orginalTime.getMinutes());
        if (time >= now.getTime()) {
            return "刚刚";
        } else if ((now.getTime() - time) < (60 * 1000)) {
            return (now.getTime() - time) / 1000 + "秒前 " + nowHourAndMinute + " ";
        } else if ((now.getTime() - time) < (60 * 60 * 1000)) {
            return (now.getTime() - time) / 1000 / 60 + "分钟前 " + nowHourAndMinute + " ";
        } else if ((now.getTime() - time) < (24 * 60 * 60 * 1000)) {
            return (now.getTime() - time) / 1000 / 60 / 60 + "小时前 " + nowHourAndMinute + " ";
        } else if (time >= nowDay) {
            return "今天 " + nowHourAndMinute;
        } else if (time >= yesterday) {
            return "昨天 " + nowHourAndMinute;
        } else {
            return toDoubleDigit(orginalTime.getMonth()) + "-" + toDoubleDigit(orginalTime.getDate()) + " "
                   + nowHourAndMinute + ":" + toDoubleDigit(orginalTime.getSeconds());
        }
    }

    /**
     * 将一位整数十位加0变成两位整数
     * 
     * @param number
     * @return
     */
    public static String toDoubleDigit(int number) {
        if (number >= 0 && number < 10) {
            return "0" + ((Integer)number).toString();
        }
        return ((Integer)number).toString();
    }

    /**
     * 得到href链接的innerHtml
     * 
     * @param href href内容
     * @return href的innerHtml
     *         <ul>
     *         <li>空字符串返回""</li>
     *         <li>若字符串不为空，且不符合链接正则的返回原内容</li>
     *         <li>若字符串不为空，且符合链接正则的返回最后一个innerHtml</li>
     *         </ul>
     * @see
     * <pre>
     *      getHrefInnerHtml(null)                                  = ""
     *      getHrefInnerHtml("")                                    = ""
     *      getHrefInnerHtml("mp3")                                 = "mp3";
     *      getHrefInnerHtml("&lt;a innerHtml&lt;/a&gt;")                    = "&lt;a innerHtml&lt;/a&gt;";
     *      getHrefInnerHtml("&lt;a&gt;innerHtml&lt;/a&gt;")                    = "innerHtml";
     *      getHrefInnerHtml("&lt;a&lt;a&gt;innerHtml&lt;/a&gt;")                    = "innerHtml";
     *      getHrefInnerHtml("&lt;a href="baidu.com"&gt;innerHtml&lt;/a&gt;")               = "innerHtml";
     *      getHrefInnerHtml("&lt;a href="baidu.com" title="baidu"&gt;innerHtml&lt;/a&gt;") = "innerHtml";
     *      getHrefInnerHtml("   &lt;a&gt;innerHtml&lt;/a&gt;  ")                           = "innerHtml";
     *      getHrefInnerHtml("&lt;a&gt;innerHtml&lt;/a&gt;&lt;/a&gt;")                      = "innerHtml";
     *      getHrefInnerHtml("jack&lt;a&gt;innerHtml&lt;/a&gt;&lt;/a&gt;")                  = "innerHtml";
     *      getHrefInnerHtml("&lt;a&gt;innerHtml1&lt;/a&gt;&lt;a&gt;innerHtml2&lt;/a&gt;")        = "innerHtml2";
     * </pre>
     */
    public static String getHrefInnerHtml(String href) {
        if (isEmpty(href)) {
            return "";
        }
        // String hrefReg = "[^(<a)]*<[\\s]*a[\\s]*[^(a>)]*>(.+?)<[\\s]*/a[\\s]*>.*";
        String hrefReg = ".*<[\\s]*a[\\s]*.*>(.+?)<[\\s]*/a[\\s]*>.*";
        Pattern hrefPattern = Pattern.compile(hrefReg, Pattern.CASE_INSENSITIVE);
        Matcher hrefMatcher = hrefPattern.matcher(href);
        if (hrefMatcher.matches()) {
            return hrefMatcher.group(1);
        }
        return href;
    }

    /**
     * 得到固定长度的随机字符串，字符串由数字和字母混合组成
     * 
     * @param length 长度
     * @return
     */
    public static String getRandomNumbersAndLetters(int length) {
        return getRandom(NUMBERS_AND_LETTERS, length);
    }

    /**
     * 得到固定长度的随机字符串，字符串由数字混合组成
     * 
     * @param length 长度
     * @return
     */
    public static String getRandomNumbers(int length) {
        return getRandom(NUMBERS, length);
    }

    /**
     * 得到固定长度的随机字符串，字符串由字母混合组成
     * 
     * @param length 长度
     * @return
     */
    public static String getRandomLetters(int length) {
        return getRandom(LETTERS, length);
    }

    /**
     * 得到固定长度的随机字符串，字符串由大写字母混合组成
     * 
     * @param length 长度
     * @return
     */
    public static String getRandomCapitalLetters(int length) {
        return getRandom(CAPITAL_LETTERS, length);
    }

    /**
     * 得到固定长度的随机字符串，字符串由小写字母混合组成
     * 
     * @param length 长度
     * @return
     */
    public static String getRandomLowerCaseLetters(int length) {
        return getRandom(LOWER_CASE_LETTERS, length);
    }

    /**
     * 得到固定长度的随机字符串，字符串由source中字符混合组成
     * 
     * @param source 源字符串
     * @param length 长度
     * @return
     *         <ul>
     *         <li>若source为null或为空字符串，返回null</li>
     *         <li>否则见{@link CommonUtils#getRandom(char[] sourceChar, int length)}</li>
     *         </ul>
     */
    public static String getRandom(String source, int length) {
        return CommonUtils.isEmpty(source) ? null : getRandom(source.toCharArray(), length);
    }

    /**
     * 得到固定长度的随机字符串，字符串由sourceChar中字符混合组成
     * 
     * @param sourceChar 源字符数组
     * @param length 长度
     * @return
     *         <ul>
     *         <li>若sourceChar为null或长度为0，返回null</li>
     *         <li>若length小于0，返回null</li>
     *         </ul>
     */
    public static String getRandom(char[] sourceChar, int length) {
        if (sourceChar == null || sourceChar.length == 0 || length < 0) {
            return null;
        }
        StringBuilder str = new StringBuilder("");
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            str.append(sourceChar[random.nextInt(sourceChar.length)]);
        }
        return str.toString();
    }

    /**
     * html的转移字符转换成正常的字符串
     * 
     * @param source
     * @return
     */
    public static String htmlEscapeCharsToString(String source) {
        if (CommonUtils.isEmpty(source)) {
            return "";
        } else {
            return source.replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&").replaceAll("&quot;",
                                                                                                              "\"");
        }
    }

    



    /**
     * 去掉字符串两边的符号，返回去掉后的结果
     * 
     * @param source 原字符串
     * @param symbol 符号
     * @return
     */
    public static String RemoveBothSideSymbol(String source, String symbol) {
        if (isEmpty(source) || isEmpty(symbol)) {
            return source;
        }

        int firstIndex = source.indexOf(symbol);
        int lastIndex = source.lastIndexOf(symbol);
        try {
            return source.substring(((firstIndex == 0) ? symbol.length() : 0),
                                    ((lastIndex == source.length() - 1) ? (source.length() - symbol.length()) : source.length()));
        } catch (IndexOutOfBoundsException e) {
            return "";
        }
    }

    /**
     * 字符串匹配(仅支持"*"匹配).
     * @param pattern 模板
     * @param str 要验证的字符串
     * @return
     */
    public static boolean simpleWildcardMatch(String pattern, String str) {
        return wildcardMatch(pattern, str, "*");
    }

    /**
     * 字符串匹配.
     * @param pattern   模板
     * @param str   要验证的字符串
     * @param wildcard 通配符
     * @return
     */
    public static boolean wildcardMatch(String pattern, String str, String wildcard) {
        if (CommonUtils.isEmpty(pattern) || CommonUtils.isEmpty(str)) {
            return false;
        }
        final boolean startWith = pattern.startsWith(wildcard);
        final boolean endWith = pattern.endsWith(wildcard);
        String[] array = CommonUtils.split(pattern, wildcard);
        int currentIndex = -1;
        int lastIndex = -1 ;
        switch (array.length) {
            case 0:
                return true ;
            case 1:
                currentIndex = str.indexOf(array[0]);
                if (startWith && endWith) {
                    return currentIndex >= 0 ;
                }
                if (startWith) {
                    return currentIndex + array[0].length() == str.length();
                }
                if (endWith) {
                    return currentIndex == 0 ;
                }
                return str.equals(pattern) ;
            default:
                for (String part : array) {
                    currentIndex = str.indexOf(part);
                    if (currentIndex > lastIndex) {
                        lastIndex = currentIndex;
                        continue;
                    }
                    return false;
                }
                return true;
        }
    }

}